home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
051-075
/
disk_075
/
comm
/
xmdmrecv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-06
|
9KB
|
350 lines
/* Comm XMODEM receive file routines */
#define XMDMRECV 1
#include "globals.h"
#include <fcntl.h>
#define STARTUP 1
#define STARTBLK 2
#define BLKNUM 3
#define COMPBLK 4
#define DATA 5
#define CHKSUM 6
#define CHKSUM1 7
static int index, state;
extern void emit_tx(), emit_rx(), emits_tx(), emits_rx();
/****************************/
/* xmodem recieve functions */
/****************************/
XMODEM_Read_File(file)
UBYTE *file;
{
extern void sendchar();
extern int readchar();
void chop_file();
UBYTE currsect, compsect, response;
USHORT dirty, syncerr, errors, blkerrok;
ULONG bytes;
unsigned int i, noresponse, errsect, naks;
int ch;
errors = errsect = naks = syncerr = noresponse = index = bytes = 0;
blkerrok = abort = dirty = FALSE;
crcflag = xfrmode;
if ((fd = creat(file, O_CREAT | O_WRONLY)) == -1)
{
sprintf(sbuff,"\nCannot Open File %s\n",file);
emits_rx(sbuff);
send_proto(CAN); send_proto( CAN );
return FALSE;
}
else
emits_rx("\nReady to Receive File -- ESC aborts transfer\n\n");
if(viewflg)
emit_vw(12);
Xconfig(TRUE); /* set serial port to 8/N/1 */
sector = 1;
if(wxflag)
if(sendWs() == TRUE)
return(WXmodem_rec(file));
response = (crcflag) ? 'C' : NAK;
state = STARTUP;
emits_rx("Waiting for initial handshake\n");
send_proto(response);
while( TRUE )
{
Process_window_event();
ch = readchar(TTIME,FALSE);
if(ch == TIMEOUT) noresponse++;
if(errors < RETRYMAX)
switch(state)
{
case STARTUP:
if(abort) return FALSE;
if( ch == TIMEOUT)
{
if(noresponse == RETRYMAX/2)
{
crcflag = (crcflag == FALSE);
response = crcflag ? 'C' : NAK;
sprintf(sbuff,"\rSender not responding. Switching to %s mode\n",
crcflag ? "CRC" : "Checksum");
emits_rx(sbuff);
}
else if(noresponse == RETRYMAX)
break;
send_proto(response);
continue;
} /* fall thru to STARTBLK state */
case STARTBLK:
if(abort) break;
switch( ch )
{
case SOH:
emit_rx_protocol(ch);
state = BLKNUM;
noresponse = 0;
response = NAK;
if(dirty)
{
movmem(xbuffer,&diskbuff[index++ * SECSIZ],SECSIZ);
dirty = FALSE;
}
break;
case EOT:
if(syncerr) continue;
emit_rx_protocol(ch);
chop_file(index);
close( fd );
send_proto( ACK );
return TRUE;
case TIMEOUT:
send_proto( NAK );
naks++; blkerrok = TRUE;
errsect = sector;
break;
default:
syncerr = 1;
break;
} /* switch( ch ) */
break;
case BLKNUM:
if(ch == TIMEOUT) break;
noresponse = 0;
emit_rx_protocol(ch);
currsect = ch;
state = COMPBLK;
if(syncerr)
if((currsect != (UBYTE)sector) && (currsect != (UBYTE)(sector - 1)))
{
if(ch == SOH )
state = BLKNUM;
else
state = STARTBLK;
}
continue;
case COMPBLK:
if(ch == TIMEOUT) break;
emit_rx_protocol(ch);
compsect = ch;
noresponse = i = checksum = crc = 0;
state = DATA;
if(syncerr)
{
if(currsect == ~compsect)
syncerr = 0;
else state = STARTBLK;
}
continue;
case DATA:
if(ch == TIMEOUT) break;
noresponse = 0;
xbuffer[ i++ ] = ch;
do_crc( ch );
if(viewflg)
emit_vw( ch );
if( i == SECSIZ)
state = CHKSUM;
continue;
case CHKSUM:
if(ch == TIMEOUT) break;
noresponse = 0;
if(crcflag)
{
state = CHKSUM1;
emit_rx_protocol(ch);
do_crc( ch );
continue;
} /* fall thru to CHKSUM1 state */
case CHKSUM1:
if(ch == TIMEOUT) break;
noresponse = 0;
emit_rx_protocol(ch);
state = STARTBLK;
response = NAK;
if(abort)
{
abort_xfer();
return FALSE;
}
if(!verify_checksum( ch ))
{
emits_rx(" Checksum error\n");
send_proto( NAK );
errsect = sector; naks++; errors++;
status(file,bytes,naks,errsect);
continue;
}
if(currsect != ~compsect)
{
emits_rx(" Bad block number received\n");
send_proto( NAK );
errsect = sector; naks++; errors++;
status(file,bytes,naks,errsect);
continue;
}
if(currsect == (UBYTE)(sector -1))
{
if(blkerrok) blkerrok = FALSE;
else
{
sprintf(sbuff," Duplicate block %d received\n",sector - 1);
emits_rx(sbuff);
}
status(file,bytes,naks,errsect);
if(check_line() == FALSE) /* if an RX char is ready */
send_proto( ACK ); /* don't send ACK */
response = ACK;
errors++;
continue;
}
if(currsect != (UBYTE)sector )
{
emits_rx(" Sector numbering error\n");
send_proto( NAK );
errsect = sector; naks++; errors++;
status(file,bytes,naks,errsect);
continue;
}
errors = 0;
bytes += SECSIZ;
dirty = TRUE;
sprintf(sbuff,"\rReceived block %d",sector);
emits_rx(sbuff);
status(file,bytes,naks,errsect);
sector++;
if(index == numbufs)
{
if(write(fd,diskbuff,numbufs * SECSIZ) != numbufs * SECSIZ)
{
emits_rx("\nERROR writing to file\n");
send_proto( CAN ); send_proto( CAN );
return FALSE;
}
index = 0;
}
if(check_line() == FALSE) /* if an RX char is ready */
send_proto( ACK ); /* don't send ACK */
response = ACK;
continue;
default:
sprintf(sbuff,"\nIllegal internal state %d\n",state);
emits_rx(sbuff);
state = STARTBLK;
continue;
} /* end switch */
if( noresponse == RETRYMAX || errors == RETRYMAX )
{
emits_rx("Maximum errors exceeded. XMODEM receive aborted\n");
abort_xfer();
return FALSE;
}
if(abort)
{
abort_xfer();
return FALSE;
}
} /* end while(TRUE) */
}
send_proto(ch)
UBYTE ch;
{
sendchar(ch);
emit_tx_protocol(ch);
}
abort_xfer()
{
int ch, errs = 0;
chop_file(index);
while((ch = readchar(1,FALSE)) != TIMEOUT)
;
while(errs++ < 3)
{
send_proto(CAN); send_proto(CAN);
if(readchar(3,FALSE) == ACK) break;
}
}
status(file,bytes,naks,errsect)
UBYTE *file;
ULONG bytes;
USHORT naks,errsect;
{
sprintf(sbuff,"File=%s bytes=%ld naks=%d [ %d ]\r",
file,bytes,naks,errsect);
status_line(0,sbuff);
}
verify_checksum( byte )
UBYTE byte;
{
if(crcflag)
{
do_crc( byte );
return (int)(crc == 0);
}
else
return ( checksum == byte );
}
/*******************************
remove pad characters from the
end of the last sector of the
file.
*******************************/
void chop_file(index)
{
int count,i;
UBYTE c;
/*
strip control Z -- CP/M and Aterm 1.4 use this for PAD character.
Don't remove NULLs. Some programs pad with NULLs. This practice
should stop, because some icon.INFO files require a NULL as the last
character in the file to terminate an ASCII string.
*/
if(chopflg)
{
for(i = SECSIZ-1; i >= 0; i--)
{
c = xbuffer[ i ];
if( c == PAD )
continue;
break;
}
}
else i = SECSIZ-1; /* not chopping, write last sector intact */
count = 0;
if(index)
count = write(fd,diskbuff,index * SECSIZ);
count += write(fd,xbuffer,++i);
if ( count != index * SECSIZ + i)
emits_rx("\nError writing file\n");
}